import { Config, Inject, Provide } from '@midwayjs/decorator';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { LoginDTO } from '../dto/login';
import { BaseError as R } from '../../../common/base.error'
import { User as UserEntity } from '../../user/entity/user'
import { TokenConfig } from '../../../interface/token.config'
import { RedisService } from '@midwayjs/redis'
import { TokenVO } from '../vo/token';
import { nanoid as uuid } from 'nanoid'
import { ResfreshTokenDTO } from '../dto/refreshToken';
import { RSAService } from '../../../common/rsa.service';
import { ErrorMessageEnums } from '../../../enums/errorMessageEnum';
// const nanoid = require('nanoid')

@Provide()
export class AuthService {
  @InjectEntityModel(UserEntity)
  authModel: Repository<UserEntity>;

  @Config('token')
  tokenConfig: TokenConfig;

  @Inject()
  redisService: RedisService;

  @Inject()
  rsaService: RSAService

  /** 登录 */
  async login(loginDto: LoginDTO) {
    const { username, password } = loginDto;
    const user = await this.authModel.createQueryBuilder('user')
    .where('user.username = :username', { username }).getOne();

    if (!user) {
      throw R.validateError(ErrorMessageEnums.USER_NOT_EXIST)
    }

    // 对比密码
    const isPwdMatch = await this.rsaService.compareStr(password, user.password);
    if (!isPwdMatch) {
      throw R.validateError('账号或密码错误!')
    }

    const { expire, refreshExpire } = this.tokenConfig;
    
    const token = uuid();
    const refreshToken = uuid();

    // 缓存
    await this.redisService.multi()
    .set(`token:${token}`, user.id)
    .expire(`token:${token}`, expire)
    .set(`refreshToken:${refreshToken}`, user.id)
    .expire(`refreshToken:${refreshToken}`, refreshExpire).exec();

    return {
      token,
      refreshToken,
      expire,
      refreshExpire
    } as TokenVO
  }

  /** 刷新token */
  async refreshToken(values: ResfreshTokenDTO) {
    const { refreshToken } = values;

    const userId = await this.redisService.get(`refreshToken:${refreshToken}`);
    if (!userId) {
      throw R.error('刷新token已失效!')
    }

    const { expire } = this.tokenConfig;
    const token = uuid();

    await this.redisService.multi()
    .set(`token:${token}`, userId)
    .expire(`token:${token}`, expire).exec();

    const refreshExpire = await this.redisService.ttl(`refreshToken:${refreshToken}`);

    return {
      token,
      refreshToken,
      expire,
      refreshExpire
    }  as TokenVO
  }

  /** 获取用户信息 */
  // async getUser

  async getUserById(userId: string) {
    return {
      menus: []
    }
  }
}